package cn.wolfcode.service.impl;

import cn.wolfcode.common.exception.BusinessException;
import cn.wolfcode.common.web.Result;
import cn.wolfcode.domain.Product;
import cn.wolfcode.domain.SeckillProduct;
import cn.wolfcode.domain.SeckillProductVo;
import cn.wolfcode.mapper.SeckillProductMapper;
import cn.wolfcode.redis.SeckillRedisKey;
import cn.wolfcode.service.ISeckillProductService;
import cn.wolfcode.web.feign.IProductFeignApi;
import cn.wolfcode.web.msg.SeckillCodeMsg;
import com.alibaba.fastjson.JSON;
import org.apache.rocketmq.spring.core.RocketMQTemplate;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;

/**
 * Created by lanxw
 */
@Service
public class SeckillProductServiceImpl implements ISeckillProductService {
    @Autowired
    private SeckillProductMapper seckillProductMapper;
    @Autowired
    private StringRedisTemplate redisTemplate;
    @Autowired
    private RocketMQTemplate rocketMQTemplate;
    @Autowired
    private IProductFeignApi productFeignApi;

    @Override
    public List<SeckillProductVo> queryByTime(Integer time) {
        // 1.查询秒杀商品的数据
        List<SeckillProduct> seckillProducts = seckillProductMapper.queryCurrentlySeckillProduct(time);
        // 2.获取对应商品的id集合
        ArrayList<Long> ids = new ArrayList<>();
        for (SeckillProduct seckillProduct : seckillProducts) {
            ids.add(seckillProduct.getProductId());
        }
        // 3.通过远程调用获取商品的集合（远程调用）
        Result<List<Product>> result = productFeignApi.queryProductByIds(ids);
        if (result == null || result.hasError()) {
            throw new BusinessException(SeckillCodeMsg.PRODUCT_SERVER_ERROR);
        }
        List<Product> products = new ArrayList<>();
        products.addAll(result.getData());
        // 将List装成map集合，方便下面查找
        HashMap<Long, Product> map = new HashMap<>();
        for (Product product : products) {
            map.put(product.getId(),product);
        }
        // 4.将秒杀商品和商品数据整合到vo中
        List<SeckillProductVo> list = new ArrayList<>();
        for (SeckillProduct seckillProduct : seckillProducts) {
            // 将秒杀商品和商品的属性拷贝到vo
            SeckillProductVo vo = new SeckillProductVo();
            Product product = map.get(seckillProduct.getProductId());
            BeanUtils.copyProperties(product,vo); //两个复制的顺序不能调换，vo的id需要是秒杀商品的id
            BeanUtils.copyProperties(seckillProduct,vo);
            list.add(vo);
        }
        return list;
    }

    @Override
    public SeckillProductVo find(Integer time, Long seckillId) {
        // 1.根据秒杀的id查询秒杀商品数据
        SeckillProduct seckillProduct = seckillProductMapper.find(seckillId);
        // 2.获取商品id，远程调用商品服务
        Result<Product> result = productFeignApi.findById(seckillProduct.getProductId());
        if (result == null || result.hasError()) {
            throw new BusinessException(SeckillCodeMsg.PRODUCT_SERVER_ERROR);
        }
        Product product = result.getData();
        // 3.将秒杀商品和商品整合到vo中
        SeckillProductVo vo = new SeckillProductVo();
        BeanUtils.copyProperties(product,vo);
        BeanUtils.copyProperties(seckillProduct,vo);
        return vo;
    }

    @Override
    public int decrStockCount(Long seckillId) {
        int count = seckillProductMapper.decrStock(seckillId);
        return count;
    }

    @Override
    public List<SeckillProductVo> queryByTimeFromCache(Integer time) {
        String key = SeckillRedisKey.SECKILL_PRODUCT_HASH.getRealKey(time + "");
        // 从缓存中获取所有指定key的所有数据
        List<Object> values = redisTemplate.opsForHash().values(key); // json字符串的集合
        List<SeckillProductVo> seckillProductVos = new ArrayList<>();
        for (Object value : values) {
            SeckillProductVo seckillProductVo = JSON.parseObject((String) value, SeckillProductVo.class);
            seckillProductVos.add(seckillProductVo);
        }
        return seckillProductVos;
    }

    @Override
    public SeckillProductVo findFromCache(Integer time, Long seckillId) {
        String key = SeckillRedisKey.SECKILL_PRODUCT_HASH.getRealKey(time + "");
        // 从缓存中获取指定的秒杀商品  redis的hash类型存储(key,hash{hashKey,hashValue})
        String hasValue = (String) redisTemplate.opsForHash().get(key, seckillId.toString());
        return JSON.parseObject(hasValue,SeckillProductVo.class);
    }


    @Override
    public int incrStock(Long seckillId) {
        int incrStock = seckillProductMapper.incrStock(seckillId);
        return incrStock;
    }

    @Override
    public void syncStockCount(Integer time, Long seckillId) {
        // 获取秒杀商品的数据库库存
        int stockCount= seckillProductMapper.getStockCount(seckillId);
        System.out.println(stockCount);
        if (stockCount > 0) {
            // 同步库存到redis中
            // 预库存key
            String key = SeckillRedisKey.SECKILL_STOCK_COUNT_HASH.getRealKey(time + "");
            redisTemplate.opsForHash().put(key, seckillId + "", stockCount + "");
        }
    }
}
